/*
 * @Author: your name
 * @Date: 2020-05-06 11:03:42
 * @LastEditTime: 2020-07-29 14:22:49
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \truck\platform\src_mgnt\download.c
 */

#include "global_common.h"
#include "src_mgnt.h"
#include "xeSqlite.h"
#include "file_space.h"
#include "read_ps_file.h"

const  char * recTopPatn="./";

static int ft_task_thread_num = 0;


typedef struct FILE_TRANSMIT {
	char name[HISOME_LEN_64];
	int listen_sockfd, send_sockfd;
	int proto;
	int mode;
	// int TID;
	// int status;
	// int value;
	struct sockaddr_in addr_peer;
	struct sockaddr_in addr_local;

	// struct timeval last_tick;
	void * priv;

    char file_name[HISOME_LEN_128];
    FILE *pFd;
    int io_fd;

    long long  receive_len;
    t_ipc_query_info ipc_info;
} file_transmit_t;

typedef struct _recordInfo{
    char          sid[HISOME_LEN_128];  
    char          ipc_SN[HISOME_LEN_128];
    char          ipc_MAC[HISOME_LEN_128];
    
    char          rec_startTime[HISOME_LEN_128];
    char          rec_endTime[HISOME_LEN_128];
    unsigned int  rec_listenPort;//srv端监听的tcp端口
    long long     rec_unUploadOffset;///断点续传使用
    long long     file_size;///断点续传使用

    // char          rec_storePath[HISOME_LEN_512];
    char          mode[HISOME_LEN_16];
    char          proto[HISOME_LEN_16];

    char          gts_sn[HISOME_LEN_128];
}recordInfo;


void update_time_for_statis_and_sysmgnt(t_ipc_query_info *ipc_info,t_ipc_statis_des *p_statis_des);

static int listen_port_base=18000;
static int listen_port_end=18100;
static int listen_port_current=18000;

static int __ft_task_TCP_listen(int sockfd) {
	struct sockaddr_in addr;
    int ret;

	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=INADDR_ANY;

	listen_port_current++;

	while ( 1) {
		if (listen_port_current>listen_port_end)
			listen_port_current=listen_port_base;

		addr.sin_port=htons(listen_port_current);
		if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr))==0)
			break;

		xeLOG_ERR("bind(%d) FAIL, %s",listen_port_current,strerror(errno));

		listen_port_current++;
	}
	ret = listen(sockfd, 5);
    if(ret < 0)
        return -1;
	return listen_port_current;
}

static int __ft_task_set_TCP_keepalive(int sockfd){
	/**
	* Aug-20-2008 by dengy<dengy@hisome.com>
	* add TCP keepalive;
	**/
	int keepAlive = 1;
	int keepIdle = 6;
	int keepInterval = 1;
	int keepCount = 3;

	/**
	* SO_KEEPALIVE
	*     Enable sending of keep-alive messages on connection-oriented sockets. 
	*     Expects a integer boolean flag.  
	**/
	setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE, (void*)&keepAlive,sizeof(keepAlive));
	/**
	* TCP_KEEPIDLE
	*     The time (in seconds) the connection needs to remain idle before TCP 
	*     starts  sending  keepalive probes, if the socket option SO_KEEPALIVE 
	*     has been set on this socket.  This option should not be used in code 
	*     intended to be portable.  
	**/
	setsockopt(sockfd,SOL_TCP, TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle));
	/**
	* TCP_KEEPINTVL
	*     The time (in seconds) between individual keepalive probes. This option
	*     should not be used in code intended to be portable.
	**/
	setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval));
	/**
	* TCP_KEEPCNT
	*	  The maximum number of keepalive probes TCP should send before dropping 
	*	  the connection. This option should not be used in code intended to be portable.  
	**/
	setsockopt(sockfd,SOL_TCP, TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount));

	return 0;
}

static int _ft_task_set_address_TCP_PASSIVE(file_transmit_t *ftp, char *address, size_t addr_len) {
	int port=0;
	// char lip[64] = {0};
	// int IP0,IP1,IP2,IP3;
	struct sockaddr_in *saip=NULL;
	int sockfd;
    ftp->listen_sockfd =-1;
    ftp->send_sockfd = -1;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd == -1) {
		xeLOG_ERR("socket FAIL, %s",strerror(errno));
		return -1;
	}

	__ft_task_set_TCP_keepalive(sockfd);
	port = __ft_task_TCP_listen(sockfd);

	ftp->listen_sockfd = sockfd;

	//filled the addr_local;
	saip=(struct sockaddr_in*)&ftp->addr_local;
	saip->sin_family      = AF_INET;
	saip->sin_addr.s_addr = INADDR_ANY;//address
	saip->sin_port        = htons(port);

	ftp->proto	= FT_TASK_PROTO_TCP;
	ftp->mode	= FT_TASK_MODE_PASSIVE;
	return 0;
}
static int _ft_task_startup(file_transmit_t *ftp){
	int ret;
	socklen_t addr_len;
	int new_sockfd = -1;
	fd_set rfds;
	char peerip[64] = {0};
	struct timeval tout;

    // ftp->pFd = fopen(ftp->file_name,"ab+");
    // if(!ftp->pFd){
    //     xeLOG_ERR("open FAIL,%s",ftp->file_name);
    //     return -1;    
    // }
    ftp->io_fd = open(ftp->file_name, O_RDWR|O_CREAT|O_APPEND, 0666);
    if (ftp->io_fd == -1) {
        xeLOG_ERR("open FAIL,%s",ftp->file_name);
        return -1;
    }
	if (ftp->proto == FT_TASK_PROTO_TCP &&
		ftp->mode == FT_TASK_MODE_PASSIVE) 
	{
		FD_ZERO(&rfds);
		FD_SET(ftp->listen_sockfd, &rfds);
		tout.tv_sec  = 10;
		tout.tv_usec = 0;

		ret = select(ftp->listen_sockfd+1, &rfds, NULL, NULL, &tout);
		if(ret == -1){
			xeLOG_INFO("%s select error, %s", ftp->name, strerror(errno));
			goto startup_out;
		}

		if ( !FD_ISSET(ftp->listen_sockfd, &rfds) ) {
			xeLOG_INFO("%s select timeout port:%d", ftp->name,(htons)(ftp->addr_local.sin_port));
			goto startup_out;
		}

		addr_len = sizeof(struct sockaddr_in);
		new_sockfd = accept(ftp->listen_sockfd, (struct sockaddr*)&ftp->addr_peer, &addr_len);
		if (new_sockfd == -1) {
			xeLOG_ERR("%s accept FAIL, %s", ftp->name,strerror(errno));
			goto startup_out;
		}

		/*close the listen socket*/
		close(ftp->listen_sockfd);
		ftp->listen_sockfd = -1;

		ftp->send_sockfd = new_sockfd;
		addr_len = sizeof(struct sockaddr_in);
		ret = getpeername(ftp->send_sockfd, (struct sockaddr*)&ftp->addr_peer, &addr_len);
		if (ret==-1) {
			xeLOG_ERR("%s getpeername FAIL, %s",ftp->name,strerror(errno));
			goto startup_out;
		}

		inet_ntop(AF_INET, &ftp->addr_peer.sin_addr, peerip, sizeof(peerip)); 
		snprintf( ftp->name, HISOME_LEN_64-1, "ch_%s_%d", 
				peerip, ntohs(ftp->addr_peer.sin_port));


        int on=1;
        ret = ioctl(ftp->send_sockfd, FIONBIO, &on);
        if(ret == -1){
            xeLOG_NOTICE("ioctl(FIONBIO) fail, %s",strerror(errno));
            return -1;
        }

        setsockopt(ftp->send_sockfd, IPPROTO_TCP, TCP_NODELAY,(void *)&on, sizeof(int));

		int no = 1;
        int recvbuflen = (1<<20);
		setsockopt(ftp->send_sockfd, IPPROTO_TCP, TCP_CORK, (char*)&no, sizeof(int));
    
        if(setsockopt(ftp->send_sockfd,SOL_SOCKET,SO_RCVBUF,(void*)&recvbuflen,sizeof(int))< 0){
            recvbuflen = (1<<20);
            setsockopt(ftp->send_sockfd,SOL_SOCKET,SO_RCVBUFFORCE,(void*)&recvbuflen,sizeof(int));
        }

        struct linger lon;
        lon.l_onoff = 1;
        lon.l_linger = 0;
        setsockopt(ftp->send_sockfd, SOL_SOCKET, SO_LINGER, &lon,sizeof(struct linger));
    
        __ft_task_set_TCP_keepalive(ftp->send_sockfd);

	}
	return 0;  

startup_out:
	if(ftp->listen_sockfd != -1)
		close(ftp->listen_sockfd);
	if(ftp->send_sockfd != -1)
		close(ftp->send_sockfd);

	ftp->listen_sockfd = -1;
	ftp->send_sockfd   = -1;

	return -1;
}

static ssize_t io_write(int io_file, const void *buf, size_t len)
{
    ssize_t n;
    int fd;
    char *p = (char *)buf;
    size_t left = len;
    size_t step = 1024 * 1024;
    int cnt = 0;
    if (io_file < 0 || buf == NULL || len == 0) {
        printf("%s paraments invalid\n", __func__);
        return -1;
    }
    fd = io_file;
    while (left > 0) {
        if (left < step)
            step = left;
        n = write(fd, (void *)p, step);
        if (n > 0) {
            p += n;
            left -= n;
            continue;
        } else if (n == 0) {
            break;
        }
        if (errno == EINTR || errno == EAGAIN) {
            if (++cnt > 3) {
                STD_print("reach max retry count");
                xeLOG_ERR("reach max retry count");
                break;
            }
            continue;
        } else {
            STD_print("write failed: %d\n", errno);
            xeLOG_ERR("reach max retry count");
            break;
        }
    }
    return (len - left);
}
static int produce_data(file_transmit_t *ftp)
{
    int ret;
    socklen_t	len = sizeof(struct sockaddr);
    #define buf_data_size (1*1024*1024)
    char buffer[buf_data_size];
    errno = 0;
    while(20200506){
        ret = recvfrom(ftp->send_sockfd, buffer, 
            buf_data_size, MSG_NOSIGNAL|MSG_DONTWAIT, (struct sockaddr*)&ftp->addr_peer, &len);
        if(ret > 0){
            int len = 0;
            // STD_print("receive size,ret:%d",ret);
            // if(ftp->pFd){
            //     len =  fwrite ((void *)buffer, 1, ret, ftp->pFd);
            //     if(len != ret){
            //         xeLOG_WARNING("receive size,ret:%d len:%d",ret,len);
            //     }
            // }
            if(ftp->io_fd > 0){
                len = io_write(ftp->io_fd,buffer,ret);
                if(len != ret){
                    xeLOG_WARNING("receive size,ret:%d len:%d",ret,len);
                    STD_print("receive size,ret:%d len:%d",ret,len);
                }
                ftp->receive_len += len;
            }
        }else{
            if ( errno == EAGAIN || errno == EWOULDBLOCK ){
                // STD_print("receive block");
                break;
            }
            xeLOG_ERR(" read fail ret:%d errno:%d,%s.close" ,ret,errno, strerror(errno));
            if(ftp->send_sockfd != -1) {
                close(ftp->send_sockfd);
                ftp->send_sockfd = -1;
            }
            // if(ftp->pFd){
            //     fflush(ftp->pFd);
            //     fclose(ftp->pFd);
            //     ftp->pFd = NULL;
            // }
            if(ftp->io_fd > 0){
                fsync(ftp->io_fd);
            }
            return -1;
        }
    }
    return 0;
}

int proc_data_after_connect_finish(file_transmit_t *ftp)
{
    int retval = -1;
    t_ipc_query_info *ipc_info = &ftp->ipc_info;
    t_ipc_file_tbl_des file_des={0};
    t_ipc_statis_des statis_des ={0};

    get_file_size_by_stat(ftp->file_name,&file_des.file_size,NULL);
    if(file_des.file_size == 0){
        xeLOG_WARNING("receive size is zero");
        return -1;
    }

    strcpy(file_des.file_name,ftp->file_name);
    file_des.file_space = ALIGN_INT(ipc_info->file_len,512);       
    file_des.start_time = ipc_info->start_time;
    file_des.end_time = ipc_info->end_time;
    file_des.duration = ipc_info->end_time -ipc_info->start_time +1;
    snprintf(file_des.detail_info_name,sizeof(file_des.detail_info_name)-1,"%s/%ld_%s",
        ipc_info->storage_path,file_des.start_time,IPC_DB_DETAIL_NAME);

    if((ipc_info->rec_offset+ftp->receive_len) != file_des.file_size){
        xeLOG_WARNING("receive_len+rec_offset not equal file_size in harddisk");
    }
    if(file_des.file_size != ipc_info->file_len){
        xeLOG_WARNING("size in harddisk not equal http para size");
        if(file_des.file_size > ipc_info->file_len){
            xeLOG_ERR("receive_len too much data, http para is :%lld,size in harddisk:%lld",
                ipc_info->file_len,file_des.file_size);

            //TODO delete
            return -1;
        }
    }

    // ps prase
    file_des.duration = my_ps_prase(file_des.file_name,file_des.detail_info_name);

    if(ipc_info->rec_offset > 0){ // 断点续传
        xeLOG_INFO("update old record");
        tiny_update_ipcdb(E_UPDATE_RECORD,ipc_info->storage_path, (void *)&file_des);
    }else{
        xeLOG_DEBUG("insert new record\n   "
            "file_des.start_time    : %ld\n" 
            "file_des.end_time      : %ld\n"
            "file_des.duration      : %d\n"
            "file_des.file_size     : %lld\n"
            "file_des.file_space    : %lld",
            file_des.start_time,
            file_des.end_time,
            file_des.duration,
            file_des.file_size,
            file_des.file_space);
        retval = tiny_update_ipcdb(E_INSERT_RECORD, ipc_info->storage_path, (void *)&file_des);
        __check_return_val_return(retval,"tiny_update_ipcdb");
        retval = tiny_get_statistics_ipcdb(ipc_info->storage_path,&statis_des);
        __check_return_val_return(retval,"tiny_get_statistics_ipcdb");
        statis_des.total_space += file_des.file_space;
        statis_des.num_files += 1;

        //update time info
        update_time_for_statis_and_sysmgnt(ipc_info,&statis_des);

    }
    return 0;
}

void * recUpload_workthread(void * arg){
    int ret = 0;
    char thread_name[128]="";
	file_transmit_t *ftp = (file_transmit_t *)arg;
    fd_set rfds,readfds;

    int port = (htons)(ftp->addr_local.sin_port);
	pthread_detach(pthread_self());
    sprintf(thread_name,"%s",ftp->ipc_info.ipc_sn);
    prctl(PR_SET_NAME, thread_name);

    ft_task_thread_num++;
	if(-1 == _ft_task_startup(ftp) ) { 
		goto ft_task_out;
	}

    int sockfd = ftp->send_sockfd;
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);

	while(20200506){
        rfds = readfds;
		// printf("wait from server write \n");
        ret = select(sockfd+1, &rfds, (fd_set *)0, 
            (fd_set *)0, (struct timeval *) 0);
		if(ret < 0){
            STD_print("select error");
            if(ftp->send_sockfd != -1) {
                close(ftp->send_sockfd);
                ftp->send_sockfd = -1;
            }
            break;
        }
		if(FD_ISSET(sockfd,&rfds)) {
            ret = produce_data(ftp);
            if(ret < 0){
                break;
            }
		}
	}
    proc_data_after_connect_finish(ftp);
ft_task_out:
    if(ftp){
        if(ftp->send_sockfd != -1) {
            close(ftp->send_sockfd);
            ftp->send_sockfd = -1;
        }
        // if(ftp->pFd){
        //     fflush(ftp->pFd);
        //     fclose(ftp->pFd);
        //     ftp->pFd = NULL;
        // }
        if(ftp->io_fd > 0){
            fsync(ftp->io_fd);
            if((-1)==posix_fadvise(ftp->io_fd, 0, 0, POSIX_FADV_DONTNEED)) {
                xeLOG_WARNING("%s posix_fadvise(POSIX_FADV_DONTNEED) fail");
            }
            close(ftp->io_fd);
        }
    }
    __free(ftp);
    ft_task_thread_num--;

	xeLOG_NOTICE("ft_task_thread(%ld): localport:%d exit!! task_num : %d", _CORE_GETTID(), port, ft_task_thread_num);
    pthread_exit(0);
}

void update_time_for_statis_and_sysmgnt(t_ipc_query_info *ipc_info,t_ipc_statis_des *p_statis_des)
{
    int ret;
    t_ipc_file_tbl_des file_des_old = {0};
    t_ipc_file_tbl_des file_des_new = {0};
    ret = get_one_record_from_ipcdb(E_QUERY_OLDEST,ipc_info->storage_path,&file_des_old);
    if(ret < 0){
        xeLOG_ERR("");
    }
    ret = get_one_record_from_ipcdb(E_QUERY_NEWEST,ipc_info->storage_path,&file_des_new);
    if(ret < 0){
        xeLOG_ERR("");
    }
    p_statis_des->start_time = file_des_old.start_time;
    p_statis_des->end_time = file_des_new.end_time;
    tiny_update_ipcdb(E_UPDATE_STATIS,ipc_info->storage_path,p_statis_des);

    ipc_info->start_time = p_statis_des->start_time;
    ipc_info->end_time = p_statis_des->end_time;     
    tiny_rec_update_sysmgntdb_tbl(E_TBL_IPCMGNT,E_UPDATE_RECORD,ipc_info);
}

/**
 * @Date: 2020-05-07 11:28:31
 * @Description: alloc space
 * @Return: 
 */
int prepare_dir_for_new_ipc(t_ipc_query_info *ipc_info)
{
    int ret;
    char tmp_sn[HISOME_LEN_64]="";
    t_space_query_info space_info = {0};
    ret = space_alloc_dir_for_new_device(&space_info);
    if(!ret){
        strcpy(ipc_info->harddisk_dir,space_info.harddisk_dir);
        strcpy(ipc_info->harddisk_sn,space_info.harddisk_sn);
    }else{
        return -1;
    }

    #if 1
    snprintf(tmp_sn,sizeof(tmp_sn)-1,"%s",ipc_info->ipc_sn);
    char *p=(char *)tmp_sn;
    while((*p)){
        // printf("%c\n",*p);
        if('/' == (*p)){
            *p = '_';
        }
        p++;
    }
    #endif
    snprintf(ipc_info->storage_path,sizeof(ipc_info->storage_path)-1,"%s/%s",
        ipc_info->harddisk_dir,tmp_sn);
    // snprintf(ipc_info->storage_path,sizeof(ipc_info->storage_path)-1,"%s/%s",
    //     ipc_info->harddisk_dir,ipc_info->ipc_sn);
    if(access(ipc_info->storage_path, F_OK) != 0){
        if(mkdir(ipc_info->storage_path, 0755) == -1){	
            STD_print("mkdir %s error \n", ipc_info->storage_path);
            return -1;
        }else{
            STD_print("mkdir %s success", ipc_info->storage_path);
        }
    }
    return ret;
}

/**
 * @Date: 2020-05-07 21:05:34
 * @Description: 
 * @Return: 
 */
int prepare_space_for_new_file(t_ipc_query_info *ipc_info)
{
    int ret = -1;
    long long free_space = 0;
    t_ipc_statis_des statis_des={0};
    long long requery_space = ipc_info->file_len;

    if(ipc_info->rec_offset > 0){
        xeLOG_NOTICE("file has exists,rec_offset:%lld",ipc_info->rec_offset);
        return 0;
    }
    ret = tiny_get_statistics_ipcdb(ipc_info->storage_path,&statis_des);
    free_space = statis_des.space_limit - statis_des.total_space;
    STD_print("requery:%lld free:%lld total:%lld, used:%lld",
        requery_space,free_space,statis_des.space_limit,statis_des.total_space);
    if(requery_space > free_space){
        int try_time = 0;
        while(requery_space > free_space){
            t_ipc_file_tbl_des file_des = {0};
            try_time++;
            if(try_time == 10){
                STD_print("what happend!!!!!!!!!!!!!!!!!");
                ret = -1;
                break;
            }
            ret = get_one_record_from_ipcdb(E_QUERY_OLDEST,ipc_info->storage_path,&file_des);
            if(ret < 0){
                xeLOG_ERR("");
                break;
            }
            free_space += file_des.file_space;
        #if 1
            tiny_update_ipcdb(E_DELETE_RECORD,ipc_info->storage_path,&file_des);
            remove(file_des.file_name);
            remove(file_des.detail_info_name);
            statis_des.total_space -= file_des.file_space;
            statis_des.num_files--;
            tiny_update_ipcdb(E_UPDATE_STATIS,ipc_info->storage_path,&statis_des);
        #endif
        }
        //TODO sync time
        update_time_for_statis_and_sysmgnt(ipc_info,&statis_des);
    }
    return ret;
}



int http_respond(MyHttpPack* req,int get_fail,char *errReason, recordInfo *p_record)
{
    cJSON *rsp,*rspHeader,*rspArr,*rspData;
    rsp=cJSON_CreateArray();
    rspHeader = cJSON_CreateObject();
    rspData = cJSON_CreateObject();
    cJSON_AddStringToObject(rspHeader,"method","POST");
    cJSON_AddStringToObject(rspHeader,"SID", p_record->sid);
    cJSON_AddStringToObject(rspHeader,"SN", p_record->ipc_SN);
    cJSON_AddItemToObject(rspHeader, "data", rspArr=cJSON_CreateArray());
    cJSON_AddItemToArray(rsp,rspHeader);
    cJSON_AddItemToArray(rspArr,rspData);

    if(get_fail){
        cJSON_AddStringToObject(rspHeader,"result","FAIL");

        cJSON_AddStringToObject(rspData,"reason",errReason);
    }else{
        cJSON_AddStringToObject(rspHeader,"result","SUCCESS");

        cJSON_AddNumberToObject(rspData,"port",p_record->rec_listenPort);
        cJSON_AddNumberToObject(rspData,"offset",p_record->rec_unUploadOffset);
    }
    com_httpPack(req->httpReq.nc,rsp);
    cJSON_Delete(rspHeader);

    return 0;
}


void src_av_upload_setup(void *data)
{
    pthread_t thread_id;
    int ret;

    int get_Fail=0;
    char errReason[HISOME_LEN_512]={'\0'};

    recordInfo record ={0};
    MyHttpPack* req =(MyHttpPack*)data; 
    cJSON *root;
    memset(&record,0,sizeof(recordInfo));
    file_transmit_t *ftp = NULL;
    root=cJSON_Parse(req->httpReq.hm->body.p);
    if (!root) {
        sprintf(errReason,"客户端发送数据有误");
        get_Fail=1;
        PRTLOG_ERR("Error before: [%s]",cJSON_GetErrorPtr());
        goto respond;
    }else{
        char value[HISOME_LEN_256];
        __prase_cjson_string(value,get_Fail,"SID",respond);
            strcpy(record.sid,value);
        __prase_cjson_string(value,get_Fail,"SN",respond);
            strcpy(record.ipc_SN,value);
        __prase_cjson_string(value,get_Fail,"MAC",respond);
            strcpy(record.ipc_MAC,value);
        __prase_cjson_string(value,get_Fail,"startTime",respond);
            strcpy(record.rec_startTime,value);
        __prase_cjson_string(value,get_Fail,"endTime",respond);
            strcpy(record.rec_endTime,value);
        __prase_cjson_string(value,get_Fail,"mode",respond);
            strcpy(record.mode,value);
        __prase_cjson_string(value,get_Fail,"filesize",respond);
            sscanf(value,"%lld",&record.file_size);

        memset(value,0,sizeof(value));
        cJSON_GetObjectValue(value,sizeof(value),root,"GTS_SN");
        if(strcmp(value,"")){
            strcpy(record.gts_sn,value);
        }else{
            xeLOG_NOTICE("GTS_SN is NULL");
        }
    }
    
	ftp = (file_transmit_t *)calloc(1, sizeof(file_transmit_t));
	if(ftp == NULL) {
		xeLOG_INFO("calloc fail");
		sprintf(errReason,"Alloc memory fail");
        get_Fail = 1;
        goto respond;
	}
    //1 query ipc_sn in sysmgnt.db
    t_ipc_query_info *ipc_info = &ftp->ipc_info;
    memset(ipc_info, 0 ,sizeof(t_ipc_query_info));
    strcpy(ipc_info->ipc_sn,record.ipc_SN);
    strcpy(ipc_info->ipc_mac,record.ipc_MAC);
    strcpy(ipc_info->collector_sn,record.gts_sn);

    ipc_info->file_len = record.file_size;
    ipc_info->start_time =  com_localTimeStr2Int(record.rec_startTime);
    ipc_info->end_time =  com_localTimeStr2Int(record.rec_endTime);

    xeLOG_DEBUG("http request\n"    \
        "\tipc_info->ipc_sn     : %s\n"    \
        "\tipc_info->ipc_mac    : %s\n"    \
        "\tipc_info->file_len   : %lld\n"    \
        "\tipc_info->start_time  : %ld\n"    \
        "\tipc_info->end_time    : %ld\n\n",
        ipc_info->ipc_sn,
        ipc_info->ipc_mac,
        ipc_info->file_len,
        ipc_info->start_time,
        ipc_info->end_time);
    tiny_rec_query_sysmgntdb_info(E_TBL_IPCMGNT,(void *)ipc_info);

    if(strcmp(ipc_info->storage_path,"")){
        xeLOG_INFO("recv upload req,ipc has register storage_path:%s",ipc_info->storage_path);
        snprintf(ftp->file_name,sizeof(ftp->file_name)-1,"%s/%ld.mp4",ipc_info->storage_path,
            ipc_info->start_time);
    }else{
        STD_print("recv upload req,ipc not register,create dir and db");
        ret = prepare_dir_for_new_ipc(ipc_info);
	    __check_return_val(ret, get_Fail,"prepare_dir_for_new_ipc fail",respond);

        // update sysmgnt db
        tiny_rec_update_sysmgntdb_tbl(E_TBL_IPCMGNT,E_INSERT_RECORD,ipc_info);

   
        //create ipc.db
        ret = tiny_ipc_db_init(ipc_info->storage_path);
	    __check_return_val(ret, get_Fail,"ipc db init fail",respond);
        

        snprintf(ftp->file_name,sizeof(ftp->file_name)-1,"%s/%ld.mp4",ipc_info->storage_path,
            ipc_info->start_time);
    }
    //2 query file  exists ? 
    if(access(ftp->file_name, F_OK) == 0){
        record.rec_unUploadOffset = ipc_info->rec_offset = get_file_size(ftp->file_name);
    }

    //3 prepare space
    ret = prepare_space_for_new_file(ipc_info);
    __check_return_val(ret, get_Fail,"prepare_space_for_new_file",respond);

	if ( !strcmp(record.mode, "PASSIVE") ) {
        char addr[32]="";
		ret = _ft_task_set_address_TCP_PASSIVE(ftp, addr, sizeof(addr));
		__check_return_val(ret, get_Fail,"listen failed",respond);
	} else if ( !strcmp(record.mode, "PORT")) {
        
    }
    record.rec_listenPort = (htons)(ftp->addr_local.sin_port);
    xeLOG_DEBUG("thread startftp->port:%d",record.rec_listenPort);

	ret = pthread_create(&thread_id, NULL, recUpload_workthread, (void*)ftp);
	__check_return_val(ret, get_Fail,"create thread fail",respond);

respond:
    if(get_Fail){
        if(ftp){
            if(ftp->send_sockfd != -1) {
                close(ftp->send_sockfd);
                ftp->send_sockfd = -1;
            }
            // if(ftp->pFd){
            //     fflush(ftp->pFd);
            //     fclose(ftp->pFd);
            //     ftp->pFd = NULL;
            // }
            if(ftp->io_fd > 0){
                fsync(ftp->io_fd);
                if((-1)==posix_fadvise(ftp->io_fd, 0, 0, POSIX_FADV_DONTNEED)) {
                    xeLOG_WARNING("%s posix_fadvise(POSIX_FADV_DONTNEED) fail");
                }
                close(ftp->io_fd);
            }
        }
        __free(ftp);
    }
    if(root)
        cJSON_Delete(root);
    http_respond(req,get_Fail,errReason,&record);

}
